03. Updating a Todo Item: Part II
Defining the handler for the route
ND004 C01 L07 03.3 Update Todo Item Walk-Through
Fixing the ordering
ND004 C01 L07 03.4 Update Todo Item Walk-Through
We're done with update!
Next up: adding the ability to delete To-Do items in our app.
Final Code
app.py
@app.route('/todos/<todo_id>/set-completed', methods=['POST'])
def set_completed_todo(todo_id):
try:
completed = request.get_json()['completed']
print('completed', completed)
todo = Todo.query.get(todo_id)
todo.completed = completed
db.session.commit()
except:
db.session.rollback()
finally:
db.session.close()
return redirect(url_for('index'))
index.html
<html>
<head>
<title>Todo App</title>
<style>
.hidden {
display: none;
}
ul {
list-style: none;
padding: 0;
margin: 0;
width: 300px;
}
li {
clear: both;
}
li button {
-webkit-appearance: none;
border: none;
outline: none;
color: red;
float: right;
cursor: pointer;
font-size: 20px;
}
.lists-wrapper, .todos-wrapper {
display: inline-block;
vertical-align: top;
}
</style>
</head>
<body>
<div class="lists-wrapper">
<ul id="lists">
{% for list in lists %}
<li>
<a href="/lists/{{ list.id }}">
{{ list.name }}
</a>
</li>
{% endfor %}
</ul>
</div>
<div class="todos-wrapper">
<h4>{{ active_list.name }}</h4>
<form id="form">
<input type="text" id="description" name="description" />
<input type="submit" value="Create" />
</form>
<div id="error" class="hidden">Something went wrong!</div>
<ul id="todos">
{% for todo in todos %}
<li>
<input class="check-completed" data-id="{{ todo.id }}" type="checkbox" {% if todo.completed %} checked {% endif %} />
{{ todo.description }}
</li>
{% endfor %}
</ul>
</div>
<script>
const checkboxes = document.querySelectorAll('.check-completed');
for (let i = 0; i < checkboxes.length; i++) {
const checkbox = checkboxes[i];
checkbox.onchange = function(e) {
const newCompleted = e.target.checked;
const todoId = e.target.dataset['id'];
fetch('/todos/' + todoId + '/set-completed', {
method: 'POST',
body: JSON.stringify({
'completed': newCompleted
}),
headers: {
'Content-Type': 'application/json'
}
})
.then(function() {
document.getElementById('error').className = 'hidden';
})
.catch(function() {
document.getElementById('error').className = '';
})
}
}
document.getElementById('form').onsubmit = function(e) {
e.preventDefault();
fetch('/todos/create', {
method: 'POST',
body: JSON.stringify({
'description': document.getElementById('description').value
}),
headers: {
'Content-Type': 'application/json'
}
})
.then(function(response) {
return response.json();
})
.then(function(jsonResponse) {
console.log(jsonResponse);
const liItem = document.createElement('LI');
liItem.innerHTML = jsonResponse['description'];
document.getElementById('todos').appendChild(liItem);
document.getElementById('error').className = 'hidden';
})
.catch(function() {
document.getElementById('error').className = '';
})
}
</script>
</body>
</html>